package com.mao.crowd.util;

import com.aliyun.api.gateway.demo.util.HttpUtils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.PutObjectResult;
import com.mao.crowd.constant.CrowdConstant;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

import javax.servlet.http.HttpServletRequest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 工具方法类
 *
 * @author maomeng
 */
public class CrowdUtil {

    /**
     * 调用发送短信的api接口
     *
     * @param host       发短信的api地址
     * @param path       发短信的服务路径
     * @param method     指定的提交方法
     * @param appcode    我方的身份验证信息，由接口服务商方面提供
     * @param mobile     要发送的手机号码
     * @param smsSignId  签名id，短信开头的那个【】里的信息
     * @param templateId 短信模板id，由接口服务商方面提供
     * @return
     */
    public static ResultEntity<String> sendShortMessage(
            String host, String path, String method, String appcode, String mobile,
            String smsSignId, String templateId) {

        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 449e6263118a42e4b87e2cf4de840e3f
        headers.put("Authorization", "APPCODE " + appcode);
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("mobile", mobile);
        // 生成随机数验证码
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            int randomNum = (int) (Math.random() * 10);
            builder.append(randomNum);
        }
        // 装入验证码替换模板
        String param = "**code**:" + builder.toString();
        querys.put("param", param);
        querys.put("smsSignId", smsSignId);
        querys.put("templateId", templateId);
        Map<String, String> bodys = new HashMap<String, String>();
        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            StatusLine statusLine = response.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            String reasonPhrase = statusLine.getReasonPhrase();
            if (200 == statusCode) {
                // 操作成功要返回生成的验证码
                return ResultEntity.successWithData(builder.toString());
            }
            return ResultEntity.failed(reasonPhrase);

        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.failed(e.getMessage());
        }
    }


    /**
     * 对明文字符串进行md5加密的方法
     *
     * @param sourcePassword 传入的明文字符串
     * @return 返回的加密字符
     */
    public static String md5(String sourcePassword) {
//        判断source的有效性，以后尽量注意这种有效性验证的步骤
        if (sourcePassword == null || sourcePassword.length() == 0) {
//            抛出自定义常量中的字符串为空异常
            throw new RuntimeException(CrowdConstant.MESSAGE_STRING_INVALIDATE);
        }
        try {
            // 获取MessageDigest对象
            String algorithm = "md5";
            MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
//            获取源密码对应的字节数组
            byte[] input = sourcePassword.getBytes();
//            执行加密操作
            byte[] output = messageDigest.digest(input);
//            创建bigInteger对象,signum为1代表正数
            int signum = 1;
            BigInteger bigInteger = new BigInteger(signum, output);
//            按照16进制将bigInteger值转换为加密字符串
            int radix = 16;
            String encoded = bigInteger.toString(radix).toUpperCase();
            return encoded;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 判断是ajax请求还是html请求
     *
     * @param request
     * @return true:ajax请求 false: 其他请求
     */
    public static boolean judgeRequestType(HttpServletRequest request) {
        String accept = request.getHeader("Accept");
        String xHeader = request.getHeader("X-Requested-With");
        String acceptJson = "application/json";
        String xHeaderJson = "XMLHttpRequest";
        boolean isJsonAccept = (accept != null && accept.contains(acceptJson));
        boolean isJsonXheader = (xHeader != null && xHeader.contains(xHeaderJson));
//        判断的是请求头里的两个字段，如果满足json的条件，就返回true
        if (isJsonAccept || isJsonXheader) {
            return true;
        }
        return false;
    }


    /**
     * 专门负责上传文件到OSS服务器的工具方法
     *
     * @param endpoint        OSS参数
     * @param accessKeyId     OSS参数
     * @param accessKeySecret OSS参数
     * @param inputStream     要上传的文件的输入流
     * @param bucketName      OSS参数
     * @param bucketDomain    OSS参数
     * @param originalName    要上传的文件的原始文件名
     * @return 包含上传结果以及上传的文件在OSS上的访问路径
     */
    public static ResultEntity<String> uploadFileToOss(
            String endpoint,
            String accessKeyId,
            String accessKeySecret,
            InputStream inputStream,
            String bucketName,
            String bucketDomain,
            String originalName) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        // 生成上传文件的目录
        String folderName = new SimpleDateFormat("yyyyMMdd").format(new Date());

        // 生成上传文件在OSS服务器上保存时的文件名
        // 原始文件名：beautfulgirl.jpg
        // 生成文件名：wer234234efwer235346457dfswet346235.jpg
        // 使用UUID生成文件主体名称
        String fileMainName = UUID.randomUUID().toString().replace("-", "");

        // 从原始文件名中获取文件扩展名
        String extensionName = originalName.substring(originalName.lastIndexOf("."));

        // 使用目录、文件主体名称、文件扩展名称拼接得到对象名称
        String objectName = folderName + "/" + fileMainName + extensionName;

        try {
            // 调用OSS客户端对象的方法上传文件并获取响应结果数据
            PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, inputStream);

            // 从响应结果中获取具体响应消息
            ResponseMessage responseMessage = putObjectResult.getResponse();

            // 根据响应状态码判断请求是否成功
            if (responseMessage == null) {

                // 拼接访问刚刚上传的文件的路径
                String ossFileAccessPath = bucketDomain + "/" + objectName;

                // 当前方法返回成功
                return ResultEntity.successWithData(ossFileAccessPath);
            } else {
                // 获取响应状态码
                int statusCode = responseMessage.getStatusCode();

                // 如果请求没有成功，获取错误消息
                String errorMessage = responseMessage.getErrorResponseAsString();

                // 当前方法返回失败
                return ResultEntity.failed("当前响应状态码=" + statusCode + " 错误消息=" + errorMessage);
            }
        } catch (Exception e) {
            e.printStackTrace();

            // 当前方法返回失败
            return ResultEntity.failed(e.getMessage());
        } finally {

            if (ossClient != null) {

                // 关闭OSSClient。
                ossClient.shutdown();
            }
        }

    }

}
